home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
dev
/
c
/
vbcc.lha
/
vbcc
/
pasm
/
directives.c
next >
Wrap
C/C++ Source or Header
|
1998-02-17
|
25KB
|
1,089 lines
/* $VER: pasm directives.c V0.8 (14.02.98)
*
* This file is part of pasm, a portable PowerPC assembler.
* Copyright (c) 1997-98 Frank Wille
*
* pasm is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
* pasm may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.8 (14.02.98) phx
* Alignment list for each section. This fixes the problems
* with optimizations.
* v0.6 (30.10.97) phx
* The names of macros will be converted to lower case (otherwise,
* they would remain inaccessible ;)
* v0.5 (12.10.97) phx
* .set directive is allowed multiple times on the same symbol.
* If a .set-assignment can't be resolved in pass 1, the symbol
* is no longer undefined, but defined with an absolute default
* value of '1'. So .ifdef will work correctly.
* .globl directive declares unknown symbols in pass 1 as
* externally defined. If the symbol is defined later in the
* source, it will be made global by add_symbol()/tables.c.
* v0.4 (29.04.97) phx
* .new_section sets type of section-symbol to SYMI_SECTION.
* New directives: .baserel
* v0.3 (10.04.97) phx
* Some vbcc-specific changes.
* v0.2 (25.03.97) phx
* Writes ELF object for 32-bit PowerPC big-endian. Either absolute
* or ELF output format may be selected. ELF is default for all
* currently supported platforms. PPCasm supports nine different
* relocation types (there are much more...).
* Compiles and works also under NetBSD/amiga (68k).
* Changed function declaration to 'new style' in all sources
* (to avoid problems with '...' for example).
* Floating pointer support. New directives: .fail, .ident, .file,
* .float, .ufloat, .double, .udouble, .local.
* v0.1 (11.03.97) phx
* First test version with all PowerPC instructions and most
* important directives. Only raw, absolute output.
* .ident and .file directives are supported, but have no effect.
* Especially floating point directives are missing.
* v0.0 (21.02.97) phx
* File created.
*/
#define DIRECTIVES_C
#include "ppcasm.h"
void activate_section(struct GlobalVars *,struct Section *);
void alignment(struct GlobalVars *,unsigned long);
char escchar(char);
static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
static char *section_attributes(struct GlobalVars *,char *,uint8 *,
uint8 *,uint8 *,uint8 *);
static void _uahalf(struct GlobalVars *,struct ParsedLine *);
static void _uaword(struct GlobalVars *,struct ParsedLine *);
static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
{
start_section(gv,pl,1);
}
static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
{
start_section(gv,pl,0);
}
static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
bool force_new)
/* define a new section with new attributes or reactivate a */
/* previously defined one */
{
struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
struct Symbol *sym;
struct AlignPoint *ap;
char *s,*name;
uint8 type,flags,protection,alignment;
s = getarg(gv,pl->operand); /* section's name */
name = remquotes(gv->strbuf);
while (nexts = (struct Section *)sec->n.next) {
if (!strcmp(name,sec->name)) {
if (force_new) { /* overwrite an old section with the same name? */
sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
name = sec->name;
sec->name = allocstring(gv->strbuf);
break;
}
else { /* reactivate old section with the same name */
s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
if (type != ST_UNDEFINED) /* attributes specified? */
if (sec->type!=type || sec->flags!=flags ||
sec->protection!=protection || sec->alignment!=alignment)
error(16); /* section attributes don't match */
pl->type = OT_SECTION;
pl->opcode = (void *)sec;
activate_section(gv,sec);
checkEOL(s);
return;
}
}
sec = nexts;
}
/* create a new section */
sec = alloczero(sizeof(struct Section));
sec->name = allocstring(name);
s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
&sec->alignment);
if (sec->type == ST_UNDEFINED) { /* set default attributes */
sec->type = ST_DATA;
sec->protection = SP_READ|SP_WRITE;
sec->alignment = 2;
}
initlist(&sec->reloclist);
initlist(&sec->xreflist);
ap = alloc(sizeof(struct AlignPoint));
ap->next = NULL;
ap->offset = ap->gap = 0;
ap->val = 1 << sec->alignment;
sec->first_align = sec->current_align = ap;
addtail(&gv->sectionlist,&sec->n);
pl->type = OT_SECTION;
pl->opcode = (void *)sec;
activate_section(gv,sec);
sym = add_symbol(gv,sec->name,SYM_RELOC,0);
sym->info = SYMI_SECTION;
checkEOL(s);
}
void activate_section(struct GlobalVars *gv,struct Section *sec)
{
gv->csect = sec; /* set active section */
gv->lcsym->relsect = sec;
gv->lcsym->value = sec->pc;
}
static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
uint8 *f,uint8 *p,uint8 *a)
/* fill in section attributes, if specified */
{
char c,*attr;
*t = ST_UNDEFINED;
*f = *p = *a = 0;
s = skipspaces(s);
if (*s) {
if (*s == ',') {
s = skipspaces(++s);
s = getarg(gv,s);
c = *gv->strbuf;
if (c=='\"' || c=='\'') {
attr = remquotes(gv->strbuf);
while (c = *attr++) {
switch (c) {
/* contents type */
case 'c':
*t = ST_CODE;
break;
case 'd':
*t = ST_DATA;
break;
case 'u':
*t = ST_UDATA;
*f |= SF_UNINITIALIZED;
break;
case 'i':
*t = ST_STRUCT;
*f |= SF_DISCARD|SF_UNINITIALIZED;
break;
/* protection */
case 'r':
*p |= SP_READ;
break;
case 'w':
*p |= SP_WRITE;
break;
case 'x':
*p |= SP_EXEC;
break;
case 's':
*p |= SP_SHARE;
break;
case 'n': /* remove and discard currently not supported */
case 'R':
break;
default:
if (c>='0' && c <='6')
*a = (uint8)(c-'0'); /* alignment */
else
error(15,c); /* illegal section attribute */
break;
}
}
}
else
error(14); /* string constant expected */
}
else if (*s != '#')
error(12); /* colon expected */
}
return (s);
}
static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
{
char *s = getsymbol(gv,pl->operand);
struct Expression exp;
struct Section *cs;
char setname[STRBUFSIZE];
struct Symbol *sym;
if (*gv->strbuf) {
strcpy(setname,gv->strbuf);
if (s = check_comma(s)) {
s = eval_expression(gv,&exp,s);
if (exp.type != SYM_UNDEF) {
if (exp.type != SYM_EXTERN) {
if (exp.type == SYM_RELOC) {
if (exp.reloctype == R_PPC_ADDR32) {
if (sym = search_symbol(gv,setname)) {
sym->value = exp.value;
sym->type = SYM_RELOC;
sym->relsect = exp.symbol->relsect;
}
else {
cs = gv->csect;
gv->csect = exp.symbol->relsect;
add_symbol(gv,setnam